﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;

using VSTalk.Engine.Core.Context;
using VSTalk.Engine.Core.XmppCommunication;
using VSTalk.Engine.Core.XmppCommunication.Services.ContactManager;
using VSTalk.Engine.Utils;
using VSTalk.Model;
using VSTalk.Tools;

namespace VSTalk.Engine.ViewModel.Editors.ContactEditor
{
    public class ContactEditorViewModel : INotifyPropertyChanged
    {
        public ContactInfo Contact { get; set; }

        public ObservableCollection<Client> Clients { get; set; }

        public RelayCommand SaveChanges { get; set; }

        public RelayCommand RejectChanges { get; set; }

        public event Action Saved;

        public event Action Rejected;

        private Client _selectedClient;

        private ISubscription _selfUnit;

        public Client SelectedClient
        {
            get { return _selectedClient; }
            set
            {
                _selectedClient = value;
                PropertyChanged.Notify(() => SelectedClient);
            }
        }

        public ContactEditorViewModel(Client client = null)
        {
            var modelContext = AppServices.Get<IModelContext>();
            Clients = new ObservableCollection<Client>(modelContext.Clients);
            Contact = new ContactInfo();
            SetCommands();
            HandleChanges();
            SelectedClient = client ?? Clients.FirstOrDefault();
        }

        private void HandleChanges()
        {
            _selfUnit = this.SubscribeToChange(() => SelectedClient, sender => sender.SelectedClient != null, sender =>
            {
                Contact.Server = SelectedClient.Server;
            });
        }

        private void SetCommands()
        {
            SaveChanges = new RelayCommand(SaveChangesExecuted, SaveChangesCanExecute);
            RejectChanges = new RelayCommand(RejectChangesExecuted);
        }

        private void RejectChangesExecuted()
        {
            OnRejected();
        }

        private bool SaveChangesCanExecute()
        {
            return !string.IsNullOrEmpty(Contact.Name) &&
                   !string.IsNullOrEmpty(Contact.Server);
        }

        private void SaveChangesExecuted()
        {
            var contactManager = CommunicationServiceFactory.Create<ContactManager>(SelectedClient);
            contactManager.AddContact(Contact);
            OnSaved();
        }

        protected virtual void OnSaved()
        {
            _selfUnit.Unsubscribe();
            var handler = Saved;
            if (handler != null) handler();
        }

        protected virtual void OnRejected()
        {
            _selfUnit.Unsubscribe();
            var handler = Rejected;
            if (handler != null) handler();
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}